from abc import abstractmethod


class Worker(object):
    def __init__(self):
        pass

    def __repr__(self):
        return '<Worker id: {} >'.format(id(self))

    @abstractmethod
    def run(self, event_data):
        """
        @run is an abstract method, class inherits
        from Worker should implement this method.

        :param event_data: dict, contains event_type and other data
        :return: result of this worker

        e.g.
        event_type = event_data.get('event_type', None)
        date = event_data.get('date', time.now())
        if event_type == 'xx':
            process_xx
            return xx
        elif event_type == 'xxx':
            process_xxx
            return xxx
        else:
            print('unknown event type')
            return x

        """
        raise NotImplementedError


class Task(object):

    def __init__(
            self,
            event_data,
            worker,
            bind_event=None,
            name=None,
            callback=None,
            **kwargs
    ):
        """
        init
        :param event_data: dict, specify event type and other data for the Worker
        :param worker: Worker, worker that defines the job to do
        :param bind_event: str, event which will run this task,
                if None, the engine thread will run this task
        :param name: str, name of this task
        :param callback: func, callback function to process the task result
        :param kwargs: params of @callback
        """
        self.bind_event = bind_event
        self.name = name
        self.event_data = event_data
        self.worker = worker
        self.callback = callback
        self.__res = None  # result from worker
        self.__task_id = id(self)
        self.__kwargs = kwargs

    def __repr__(self):
        return '<Task task id: {}, bind_event: {}, name: {}, ' \
               'event_type: {}, worker: {}'.format(
                self.__task_id,
                self.bind_event,
                self.name,
                self.event_data.get('event_type', None),
                self.worker
            )

    def do(self):
        self.__res = self.worker.run(self.event_data)
        if self.callback:
            self.callback(self.__res, **self.__kwargs)

    @property
    def result(self):
        return {
            'task_id': self.__task_id,
            'task_name': self.name,
            'task_result': self.__res
        }
